#include "qscalewidget.h"

#include "../../libs/shared/property/qabstractproperty.h"
#include "../../libs/shared/qpropertyfactory.h"
#include "../../libs/shared/qcommonstruct.h"
#include "../../libs/shared/qhostfactory.h"

#include <QPainter>
#include <QGradient>

QScaleWidget::QScaleWidget(QWidget *parent):
    QAbstractGraphicsWidget(parent)
{
}

void QScaleWidget::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    m_text_brush=QBrush(property("text_color").value<QGradient>());
    p.setRenderHint(QPainter::Antialiasing,m_antialiasing);
    p.setPen(m_pen);
    p.setRenderHint(QPainter::TextAntialiasing,true);
    if(m_type==ST_Horizontal)
    {
        draw_horizontal(&p);
    }
    else if(m_type==ST_Vertical)
    {
        draw_vertical(&p);
    }
}

void QScaleWidget::update_text()
{
    m_texts.clear();
    QString str;
    for(int i=0;i<=m_main_count;i++)
    {
        str.sprintf(m_format.toLocal8Bit(),m_max-(m_max-m_min)*i/m_main_count);
        if(m_invertedAppearance)
        {
            m_texts.append(str);
        }
        else
        {
            m_texts.insert(0,str);
        }
    }
}

void QScaleWidget::draw_horizontal(QPainter *p)
{
    int wid=0;

    foreach(QString str,m_texts)
    {
        QFontMetrics fm(p->font());
        if(wid<fm.width(str))
        {
            wid=fm.width(str);
        }
    }

    QRect re=rect();
    if(m_textVisible)
    {
        if(m_text_position==TP_POSITION_1)
        {
            re.adjust(0,qMax(font().pointSize()/2,m_pen_info.m_width/2)+2,
                      -wid-4,
                      -qMax(font().pointSize()/2,m_pen_info.m_width/2)-2);
        }
        else if(m_text_position==TP_POSITION_2)
        {
            re.adjust(wid+4,
                      qMax(font().pointSize()/2,m_pen_info.m_width/2)+2,-1,
                      -qMax(font().pointSize()/2,m_pen_info.m_width/2)-2);
        }
    }
    else
    {
        re.adjust(0,0,-1,-1);
    }

    QPen pen;
    for(int i=0;i<=m_main_count;i++)
    {
        p->setPen(m_pen);
        p->drawLine(re.left(),re.top()+re.height()*i/m_main_count,re.right(),re.top()+re.height()*i/m_main_count);

        if(i<m_main_count)
        {
            int s=re.top()+re.height()*i/m_main_count;
            int e=re.top()+re.height()*(i+1)/m_main_count;
            int r=m_text_position==TP_POSITION_1?(re.left()):(re.left()+re.width()/2);
            int l=m_text_position==TP_POSITION_1?(re.left()+re.width()/2):(re.right());
            for(int i=1;i<m_subsidiary_count;i++)
            {
                p->drawLine(l,s+(e-s)*i/m_subsidiary_count,r,s+(e-s)*i/m_subsidiary_count);
            }
        }
        if(m_textVisible)
        {
            pen=p->pen();
            pen.setBrush(m_text_brush);
            p->setPen(pen);
            if(m_text_position==TP_POSITION_1)
            {
                p->drawText(QRect(re.right(),re.top()+re.height()*i/m_main_count-font().pointSize()/2-4,
                                  wid+4,font().pointSize()+8),Qt::AlignCenter,m_texts.at(m_main_count-i));
            }
            else if(m_text_position==TP_POSITION_2)
            {
                p->drawText(QRect(0,re.top()+re.height()*i/m_main_count-font().pointSize()/2-4,
                                  wid+4,font().pointSize()+8),Qt::AlignCenter,m_texts.at(m_main_count-i));
            }
        }
    }
}

void QScaleWidget::draw_vertical(QPainter *p)
{
    QRect re=rect();
    int wid=0;

    foreach(QString str,m_texts)
    {
        QFontMetrics fm(p->font());
        if(wid<fm.width(str))
        {
            wid=fm.width(str);
        }
    }
    if(m_textVisible)
    {
        if(m_text_position==TP_POSITION_1)
        {
            re.adjust(qMax(m_pen_info.m_width/2,wid/2)+2,
                      0,-qMax(m_pen_info.m_width/2,wid/2)-2,
                      -font().pointSize()-8);
        }
        else if(m_text_position==TP_POSITION_2)
        {
            re.adjust(qMax(m_pen_info.m_width/2,wid/2)+2,
                      font().pointSize()+8,
                      -qMax(m_pen_info.m_width/2,wid/2)-2,0);
        }
    }
    else
    {
        re.adjust(0,0,-1,-1);
    }
    QPen pen;
    for(int i=0;i<=m_main_count;i++)
    {
        p->setPen(m_pen);
        p->drawLine(re.left()+re.width()*i/m_main_count,re.top(),re.left()+re.width()*i/m_main_count,re.bottom());
        if(i<m_main_count)
        {
            int s=re.left()+re.width()*i/m_main_count;
            int e=re.left()+re.width()*(i+1)/m_main_count;
            int t=m_text_position==TP_POSITION_1?(re.top()):(re.top()+re.height()/2);
            int b=m_text_position==TP_POSITION_1?(re.top()+re.height()/2):(re.bottom());
            for(int i=1;i<m_subsidiary_count;i++)
            {
                p->drawLine(s+(e-s)*i/m_subsidiary_count,t,s+(e-s)*i/m_subsidiary_count,b);
            }
        }
        if(m_textVisible)
        {
            pen=p->pen();
            pen.setBrush(m_text_brush);
            p->setPen(pen);
            if(m_text_position==TP_POSITION_1)
            {
                p->drawText(QRect(re.left()+re.width()*i/m_main_count-wid/2,re.bottom(),wid,font().pointSize()+8),Qt::AlignCenter,m_texts.at(i));
            }
            else if(m_text_position==TP_POSITION_2)
            {
                p->drawText(QRect(re.left()+re.width()*i/m_main_count-wid/2,0,wid,font().pointSize()+8),Qt::AlignCenter,m_texts.at(i));
            }
        }
    }
}

int QScaleWidget::mainCount()
{
   return m_main_count;
}

void QScaleWidget::setMainCount(int count)
{
    if(count<=0)
    {
        return;
    }
    if(m_main_count!=count)
    {
        m_main_count=count;
        update_text();
        update();
    }
}


int QScaleWidget::subsidiaryCount()
{
   return m_subsidiary_count;
}

void QScaleWidget::setSubsidiaryCount(int count)
{
    if(count<0)
    {
        return;
    }
    if(m_subsidiary_count!=count)
    {
        m_subsidiary_count=count;
        update();
    }
}

void QScaleWidget::setFormat(const QString &str)
{
    if(m_format!=str)
    {
        m_format=str;
        update_text();
        update();
    }
}

void QScaleWidget::setMaxValue(double value)
{
    if(value<=m_min)
    {
        return;
    }
    value=(int(value*1000000))/1000000.0;
    if(m_max!=value)
    {
        m_max=value;
        update_text();
        update();
    }
}

double QScaleWidget::maxValue()
{
    return m_max;
}

void QScaleWidget::setMinValue(double value)
{
    if(value>=m_max)
    {
        return;
    }
    value=(int(value*1000000))/1000000.0;
    if(m_min!=value)
    {
        m_min=value;
        update_text();
        update();
    }
}

double QScaleWidget::minValue()
{
    return m_min;
}

void QScaleWidget::setInvertedAppearance(bool invertedAppearance)
{
    if(m_invertedAppearance!=invertedAppearance)
    {
        m_invertedAppearance=invertedAppearance;
        update_text();
        update();
    }
}

bool QScaleWidget::invertedAppearance()
{
    return m_invertedAppearance;
}

void QScaleWidget::setTextPosition(int textPosition)
{
    if(m_text_position!=textPosition)
    {
        m_text_position=textPosition;
        update();
    }
}

int QScaleWidget::textPosition()
{
    return m_text_position;
}

bool QScaleWidget::textVisible()
{
    return m_textVisible;
}

void QScaleWidget::setTextVisible(bool textVisible)
{
    if(m_textVisible!=textVisible)
    {
        m_textVisible=textVisible;
        update();
    }
}

QString QScaleWidget::format()
{
    return m_format;
}

int QScaleWidget::type()
{
    return m_type;
}

void QScaleWidget::setType(int type)
{
    if(m_type!=type)
    {
        m_type=type;
        update();
    }
}


QScaleWidgetHost::QScaleWidgetHost(QAbstractHost *parent):
    QAbstractGraphicsHost(parent)
{
    setProperty("need_frame",false);
}

void QScaleWidgetHost::create_object()
{
    m_object=new QScaleWidget;
    m_object->setObjectName("scaleWidget");
}

QString QScaleWidgetHost::get_show_name()
{
    return tr("Scale");
}

QString QScaleWidgetHost::get_show_group()
{
    return tr("Base Graphics");
}

QString QScaleWidgetHost::get_show_icon()
{
    return ":/base_grahpics_images/scale.png";
}

void QScaleWidgetHost::init_property()
{
    QAbstractGraphicsHost::init_property();

    QAbstractProperty* pro;

    pro=get_property("font");
    if(pro!=NULL)
    {
        pro->set_attribute(ATTR_VISIBLE,true);
    }

    remove_property("antialiasing");

    pro=get_property("pen");
    if(pro!=NULL)
    {
        pro->set_attribute("pen_join_style:Visible",false);
        pro->set_attribute("pen_cap_style:Visible",false);
    }

    QScaleWidget* wid=(QScaleWidget*)m_object;

    pro=QPropertyFactory::create_property("ByteArray");
    if(pro!=NULL)
    {
        pro->set_property("name","format");
        pro->set_attribute("show_name",tr("Text Format"));
        pro->set_attribute("group","Attributes");
        m_object->setProperty("format","%0.1f");
        pro->set_attribute(ATTR_CAN_SAME,true);
        insert_property(pro);
    }

    pro=QPropertyFactory::create_property("Number");
    if(pro!=NULL)
    {
        pro->set_property("name","main_count");
        pro->set_attribute("show_name",tr("Main Scale"));
        pro->set_attribute("group","Attributes");
        m_object->setProperty("main_count",10);
        insert_property(pro);
    }

    pro=QPropertyFactory::create_property("Number");
    if(pro!=NULL)
    {
        pro->set_property("name","subsidiary_count");
        pro->set_attribute("show_name",tr("Subsidiary Scale"));
        pro->set_attribute("group","Attributes");
        m_object->setProperty("subsidiary_count",0);
        insert_property(pro);
    }

    pro=QPropertyFactory::create_property("Float");
    if(pro!=NULL)
    {
        pro->set_property("name","minValue");
        pro->set_attribute("show_name",tr("Min Value"));
        pro->set_attribute("group","Attributes");
        m_object->setProperty("minValue",0.0);
        pro->set_attribute(ATTR_CAN_SAME,true);
        insert_property(pro);
    }

    pro=QPropertyFactory::create_property("Float");
    if(pro!=NULL)
    {
        pro->set_property("name","maxValue");
        pro->set_attribute("show_name",tr("Max Value"));
        pro->set_attribute("group","Attributes");
        m_object->setProperty("maxValue",100.0);
        pro->set_attribute(ATTR_CAN_SAME,true);
        insert_property(pro);
    }

    pro=QPropertyFactory::create_property("Color");
    if(pro!=NULL)
    {
        pro->set_property("name","text_color");
        pro->set_attribute("show_name",tr("Text Color"));
        pro->set_attribute("group","Attributes");
        m_object->setProperty("text_color",pro->get_value());
        pro->set_attribute(ATTR_CAN_SAME,true);
        connect(pro,SIGNAL(refresh()),wid,SLOT(update()));
        insert_property(pro);
    }

    pro=QPropertyFactory::create_property("Enum");
    if(pro!=NULL)
    {
        pro->set_property("name","type");
        pro->set_attribute("show_name",tr("Type"));
        pro->set_attribute("group","Attributes");
        pro->set_attribute(ATTR_CAN_SAME,true);
        ComboItems items;
        tagComboItem item;
        item.m_text="Horizontal";
        item.m_value=ST_Horizontal;
        items.append(item);
        item.m_text="Vertical";
        item.m_value=ST_Vertical;
        items.append(item);
        QVariant v;
        v.setValue<ComboItems>(items);
        pro->set_attribute("items",v);
        m_object->setProperty("type",ST_Horizontal);
        insert_property(pro);
    }

    pro=QPropertyFactory::create_property("Enum");
    if(pro!=NULL)
    {
        pro->set_property("name","textPosition");
        pro->set_attribute("show_name",tr("Position"));
        pro->set_attribute("group","Attributes");
        pro->set_attribute(ATTR_CAN_SAME,true);
        ComboItems items;
        tagComboItem item;
        item.m_text="Position 1";
        item.m_value=TP_POSITION_1;
        items.append(item);
        item.m_text="Position 2";
        item.m_value=TP_POSITION_2;
        items.append(item);
        QVariant v;
        v.setValue<ComboItems>(items);
        pro->set_attribute("items",v);
        m_object->setProperty("textPosition",TP_POSITION_1);
        insert_property(pro);
    }

    pro=QPropertyFactory::create_property("Bool");
    if(pro!=NULL)
    {
        pro->set_property("name","textVisible");
        pro->set_attribute("show_name",tr("Text Visible"));
        pro->set_attribute("group","Attributes");
        m_object->setProperty("textVisible",true);
        pro->set_attribute(ATTR_CAN_SAME,true);
        insert_property(pro);
    }

    pro=QPropertyFactory::create_property("Bool");
    if(pro!=NULL)
    {
        pro->set_property("name","invertedAppearance");
        pro->set_attribute("show_name",tr("Inverted"));
        pro->set_attribute("group","Attributes");
        m_object->setProperty("invertedAppearance",false);
        pro->set_attribute(ATTR_CAN_SAME,true);
        insert_property(pro);
    }

    set_property_value("geometry",QRect(0,0,50,200));
}

void QScaleWidgetHost::setType(int type)
{
    set_property_value("type",type);
}

int QScaleWidgetHost::type()
{
    return get_property_value("type").toInt();
}

void QScaleWidgetHost::set_max_value(double value)
{
    set_property_value("maxValue",value);
}

double QScaleWidgetHost::max_value()
{
    return get_property_value("maxValue").toDouble();
}

void QScaleWidgetHost::set_min_value(double value)
{
    set_property_value("minValue",value);
}

double QScaleWidgetHost::min_value()
{
    return get_property_value("minValue").toDouble();
}

void QScaleWidgetHost::set_text_visible(bool visible)
{
    set_property_value("textVisible",visible);
}

bool QScaleWidgetHost::text_visible()
{
    return get_property_value("textVisible").toBool();
}


qRegisterHost("basegraphics.scale",QScaleWidgetHost,5070)
